package ru.amse.tsyganov.jumleditor.view.collaboration;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.swt.graphics.GC;

import ru.amse.tsyganov.jumleditor.graphicaleditor.Coordinates;
import ru.amse.tsyganov.jumleditor.model.collaboration.Message;
import ru.amse.tsyganov.jumleditor.model.common.Edge;
import ru.amse.tsyganov.jumleditor.model.common.GraphModel;
import ru.amse.tsyganov.jumleditor.properties.EnumProperty;
import ru.amse.tsyganov.jumleditor.properties.NoEmptyStringProperty;
import ru.amse.tsyganov.jumleditor.properties.StringProperty;
import ru.amse.tsyganov.jumleditor.validator.Problem;
import ru.amse.tsyganov.jumleditor.view.ConnectionPoint;
import ru.amse.tsyganov.jumleditor.view.ViewVisitor;
import ru.amse.tsyganov.jumleditor.view.activepoints.ActivePoint;
import ru.amse.tsyganov.jumleditor.view.activepoints.MessageActivePoint;
import ru.amse.tsyganov.jumleditor.view.common.EdgeView;
import ru.amse.tsyganov.jumleditor.view.common.GraphView;
import ru.amse.tsyganov.jumleditor.view.lines.LinePainter;
import ru.amse.tsyganov.jumleditor.view.lines.SimpleLine;
import ru.amse.tsyganov.jumleditor.view.preferences.Colors;

public class MessageView<T extends Message> extends EdgeView<T> {
	
	public MessageView(T model,
			GraphView<? extends GraphModel> activityGraphView,
			ConnectionPoint sourceConnectionPoint,
			ConnectionPoint targetConnectionPoint) {
		
		super(model, activityGraphView, sourceConnectionPoint, 
				targetConnectionPoint);
		
		initProperties();
	}
	
	
	@Override
	public void accept(ViewVisitor v) {
		v.visitMessageView(this);
	}
	
	@Override
	public void paint(GC gc, Coordinates coordinates) {
		assert gc != null;
		
		gc.setForeground(getValidity().getColor());
		gc.setBackground(getValidity().getColor());
		
		LinePainter.drawArrowedLine(gc, coordinates, getBrokenLine());
				
		drawString(gc, coordinates);
		
		gc.setForeground(Colors.getBlackColor());
		gc.setBackground(Colors.getBlackColor());
		int len = 15;
		SimpleLine line;
		if (getBrokenLine()[0].isHorizontal()) {
			if (getBrokenLine()[0].getX1() < getBrokenLine()[0].getX2()) {
				line = new SimpleLine(
						getTextOutputPoint().x - len, 
						getTextOutputPoint().y + getStringExtent().y / 2 + 5,
						getTextOutputPoint().x + len, 
						getTextOutputPoint().y + getStringExtent().y / 2 + 5);
			} else {
				line = new SimpleLine(
						getTextOutputPoint().x + len, 
						getTextOutputPoint().y + getStringExtent().y / 2 + 5,
						getTextOutputPoint().x - len, 
						getTextOutputPoint().y + getStringExtent().y / 2 + 5);
			}
		} else {
			if (getBrokenLine()[0].getY1() < getBrokenLine()[0].getY2()) {
				line = new SimpleLine(
						getTextOutputPoint().x - getStringExtent().x / 2 - 5, 
						getTextOutputPoint().y - len,
						getTextOutputPoint().x - getStringExtent().x / 2 - 5, 
						getTextOutputPoint().y + len);
			} else {
				line = new SimpleLine(
						getTextOutputPoint().x - getStringExtent().x / 2 - 5, 
						getTextOutputPoint().y + len,
						getTextOutputPoint().x - getStringExtent().x / 2 - 5, 
						getTextOutputPoint().y - len);
			}
		}
		if (getModel().isSynchronous()) {
			LinePainter.drawArrowedLine(gc, coordinates, line, true);
		} else {
			LinePainter.drawHalfArrowedLine(gc, coordinates, line, true);
		}
	}
	
	@Override
	public String getText() {
		String text = getModel().getSequenceNumber();
		if (getModel().getCondition().length() > 0) {
			text += " [" + getModel().getCondition() + "]"; 
		}
		if (getModel().getIteration().length() > 0) {
			text += " *[" + getModel().getIteration() + "]"; 
		}
		text += " : ";
		if (getModel().getReturnValue().length() > 0) {
			text += getModel().getReturnValue() + " := ";
		}
		if (getModel().getOperation().length() > 0) {
			text += getModel().getOperation();
		}
		text += "(";
		if (getModel().getArgument().length() > 0) {
			text += getModel().getArgument();
		}
		text += ")";
		return text;
	}

	private void initProperties() {
		
		super.getProperties().addProperty(new NoEmptyStringProperty("Operation") {

			@Override
			public String getPropertyValue() {
				return getModel().getOperation();
			}

			@Override
			public void setPropertyValue(String newValue) {
				getModel().setOperation(newValue);
			}
			
		});
		
		super.getProperties().addProperty(new StringProperty("Argument") {

			@Override
			public String getPropertyValue() {
				return getModel().getArgument();
			}

			@Override
			public void setPropertyValue(String newValue) {
				getModel().setArgument(newValue);
			}
			
		});
		
		super.getProperties().addProperty(new StringProperty("Return value") {

			@Override
			public String getPropertyValue() {
				return getModel().getReturnValue();
			}

			@Override
			public void setPropertyValue(String newValue) {
				getModel().setReturnValue(newValue);
			}
			
		});
		
		super.getProperties().addProperty(new StringProperty("Sequence number") {

			@Override
			public String getPropertyValue() {
				return getModel().getSequenceNumber();
			}

			@Override
			public void setPropertyValue(String newValue) {
				getModel().setSequenceNumber(newValue);
			}
			
		});
		
		super.getProperties().addProperty(new StringProperty("Condition") {

			@Override
			public String getPropertyValue() {
				return getModel().getCondition();
			}

			@Override
			public void setPropertyValue(String newValue) {
				getModel().setCondition(newValue);
			}
			
		});
		
		super.getProperties().addProperty(new StringProperty("Iteration") {

			@Override
			public String getPropertyValue() {
				return getModel().getIteration();
			}

			@Override
			public void setPropertyValue(String newValue) {
				getModel().setIteration(newValue);
			}
			
		});
		
		super.getProperties().addProperty(new EnumProperty("Synchronization",
				new String[] {"Synchronous", "Asynchronous"}) {

			@Override
			public Integer getPropertyValue() {
				return getModel().isSynchronous() ? 0 : 1;
			}

			@Override
			public void setPropertyValue(Integer newValue) {
				getModel().setSynchronous(newValue == 0);
			}
			
		});
	}
	
	@Override
	public StringProperty getMainProperty() {
		return null;
	}

	public String getClassName() {
		return "TransitionView";
	}

	@Override
	public List<Problem> getInnerProblems() {
		return Collections.emptyList();
	}

	@Override
	public List<ActivePoint> createActivePoints() {
		List<ActivePoint> points = new ArrayList<ActivePoint>(2);
		MessageActivePoint startPoint = new MessageActivePoint(true) {
			@Override
			public int getCurrentActivePointX() {
				return getStartPoint().x;
			}
			@Override
			public int getCurrentActivePointY() {
				return getStartPoint().y;
			}
			@Override
			public EdgeView<? extends Edge> getEdgeView() {
				return MessageView.this;
			}
			@Override
			public GraphView<? extends GraphModel> getContainer() {
				return getActivityGraphView();
			}
		};
		
		MessageActivePoint endPoint = new MessageActivePoint(false) {
			@Override
			public int getCurrentActivePointX() {
				return getEndPoint().x;
			}
			@Override
			public int getCurrentActivePointY() {
				return getEndPoint().y;
			}
			@Override
			public EdgeView<? extends Edge> getEdgeView() {
				return MessageView.this;
			}
			@Override
			public GraphView<? extends GraphModel> getContainer() {
				return getActivityGraphView();
			}
		};
		points.add(startPoint);
		points.add(endPoint);
		return points;
	}
}
